﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;

using Daybreak.Core.Mathematics;

namespace Daybreak.Core.Geometrics
{
    public abstract class Primitive
    {
        #region PrimitiveProperties

        public struct Properties
        {
            public enum MassDistributionKind
            {
                Solid, Shell
            }

            /// <summary>
            /// density is mass per volume of SOLID, otherwise mass per surface area
            /// </summary>
            public enum MassKind
            {
                Mass, Density
            }

            public MassKind MassType;
            public MassDistributionKind MassDistribution;
            public float MassOrDensity;

            public Properties(MassDistributionKind massDistribution, MassKind massType, float massOrDensity)
            {
                this.MassDistribution = massDistribution;
                this.MassOrDensity = massOrDensity;
                this.MassType = massType;
            }

        }

        #endregion

        public static void CreatePlane(ref Vector3 n, ref Vector3 pos, out Plane p)
        {
            //Plane p = new Plane();
            //MathEngine.NormalizeSafe(ref n);
            p.Normal = n;

            Vector3.Dot(ref n, ref pos, out p.D);

            p.D = -p.D;

        }


        /// <summary>
        /// Must support intersection with a segment (ray cast)
        /// </summary>
        /// <param name="frac"></param>
        /// <param name="normal"></param>
        /// <param name="seg"></param>
        /// <returns></returns>
        public abstract bool SegmentIntersect(out float frac, out Vector3 pos,
            out Vector3 normal, ref Segment seg);

        /// <summary>
        /// Calculate and return the volume
        /// </summary>
        /// <returns></returns>
        public abstract float GetVolume();

        /// <summary>
        /// Calculate and return the surface area
        /// </summary>
        /// <returns></returns>
        public abstract float GetSurfaceArea();

        /// <summary>
        /// Returns the mass, center of mass, and intertia tensor around the origin
        /// </summary>
        /// <param name="primitiveProperties"></param>
        /// <param name="mass"></param>
        /// <param name="centerOfMass"></param>
        /// <param name="inertiaTensor"></param>
        public abstract void GetMassProperties(Properties primitiveProperties,
            out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor);

        /// <summary>
        /// Returns a bounding box that covers this primitive. Default returns a huge box, so
        /// implement this in the derived class for efficiency
        /// </summary>
        /// <returns></returns>
        public virtual void GetBoundingBox(out BoundingBox box)
        {
            box = new BoundingBox();
        }

    }
}
